    // * ----------------------------
    // *
    // * Modbus server: NT117 v0.0.3
    // *
    // * ----------------------------

    #include <stdio.h>
    #include <limits.h>
    #include <ctype.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <signal.h>

    #include <modbus.h>

    #if defined(_WIN32)
    #include <ws2tcpip.h>
    #else
    #include <sys/select.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #endif

    enum
    {
    	TCP,
    	RTU
    };

    // Method: Out masseg.
    void msg_printf(char info, char* msg)
    {
    	printf("[%c] - %s\n", info, msg);
    }

    int main(int argc, char **argv)
    {
    	const char W = '?';
    	const char I = '*';
    	const char A = '!';

    	char *ip = NULL;
    	char *port = NULL;

    	int s = -1; // Server socket.

    	uint8_t *query;
    	modbus_t *ctx = NULL;
    	modbus_mapping_t *mb_mapping = NULL;
    	int rc;
    	int use_backend;
    	int header_length;

    	// Console menu.
    	printf("---== Test Modbus SERVER (mod.: NT117 v1.0.3). ==---\n");
    	printf("\033[96m");
    	if(argc > 1)
    	{
    		if(strcmp(argv[1], "tcp") == 0)
    		{
    			msg_printf(I, "Set TCP connection.");
    			use_backend = TCP;
    			// todo: TCP connection.
    			printf("[-_0]: todo - TCP connection.");
    			exit(1);
    		}
    		else if(strcmp(argv[1], "rtu") == 0)
    		{
    			msg_printf(I, "Set RTU connection.");
    			use_backend = RTU;
    			// todo: RTU conection.
    			printf("[0_-]: todo - RTU connection.");
    			exit(1);
    		}
    		else if(strcmp(argv[1], "-d") == 0)
    		{
    			msg_printf(I, "Set default option.");
    			ip = "192.168.0.106";
    			port = "502";

    			ctx = modbus_new_tcp_pi(ip, port);
    			query = malloc(MODBUS_TCP_MAX_ADU_LENGTH); // length = 260 (modbus-tcp.h)
    		}
    		else if(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
    		{
    			printf("\033[93m");
    			printf("Help menu. Reference: sudo ./mb-s <key> (sudo ./mb-s -d) \n");
    			printf("\033[0m");
    			msg_printf(I, "<-h> or <--help> \033[90m...|\033[0m Call help menu.");
    			msg_printf(I, "<tcp> \033[90m..............|\033[0m Create TCP connection.");
    			msg_printf(I, "<etu> \033[90m..............|\033[0m Create RTU connection.");
    			msg_printf(I, "<-d> \033[90m...............|\033[0m Set options program.");
    			printf("\033[0m");
    			exit(1);
    		}
    		else
    		{
    			printf("\033[93m");
    			msg_printf(W, "Unknow key...");
    			printf("\033[0m");
    			exit(1);
    		}
    	}
    	else
    	{
    		printf("\033[91m");
    		msg_printf(A, "Pleace set key for run Server!!!");
    		msg_printf(I, "Helper key -h or --help.");
    		exit(1);
    	}
    	printf("\033[0m");

    	// todo: Improve the output of information about the type of connection.
    	printf("[<] - IP Address - %s | Port - %s\n", ip, port);

    	msg_printf(I, "Config modbus server.");

    	header_length = modbus_get_header_length(ctx);

    	msg_printf(I, "Activate DEBUG mod. (OFF)");
    	modbus_set_debug(ctx, 0); // activate debug mod ON = 1 || OFF = 0

    	msg_printf(I, "Creat MB Map...");

    	// Creation memmory map for this server.
    	// Descriptions data:
    	// Coil = 0x2 (type: bool)
    	// Input discret = 0x2 (type: bool)
    	// Holding = 0x2 (type: int)
    	// Input register = 0x2 (type: int)
    	unsigned int st = 2;
    	unsigned int nb = 2;
    	mb_mapping = modbus_mapping_new_start_address(st, nb, st, nb, st, nb, st, nb);

    	// Checking memmory map modbus server.
    	if(mb_mapping == NULL)
    	{
    		printf("\033[91m");
    		fprintf(stderr, "Failed to allocate the mapping: %s\n", modbus_strerror(errno));
    		modbus_free(ctx);
    		printf("\033[0m");
    		return -1;
    	}

    	msg_printf(I, "Initialize values fo MB Map.");

    	// Input register 0x0002 = 17
    	msg_printf(I, "Input register 0x0002 = 17");
    	mb_mapping->tab_input_registers[0] = 0x0012;
    	msg_printf(I, "Next step..(25%)");

    	// Holding register 0x0002 = 50
    	msg_printf(I, "Holding register 0x0002 = 50");
    	mb_mapping->tab_registers[0] = 50;
    	msg_printf(I, "Next step..(50%)");

    	// Discret input register 0x02 = true
    	msg_printf(I, "Discret input register 0x0002 = true");
    	mb_mapping->tab_input_bits[0] = 1;
    	msg_printf(I, "Next step..(75%)");

    	// Coil register 0x0002 = false
    	msg_printf(I, "Coil register 0x0002 = false");
    	mb_mapping->tab_bits[0] = 0;
    	msg_printf(I, "Good! (100%). Init. completed!");

    	// Start modbus server.
    	msg_printf(I, "Start Server...");
     	// Start listen server socket.
    	s = modbus_tcp_pi_listen(ctx, 1);
    	// Start accept a new connection on a TCP.
    	modbus_tcp_pi_accept(ctx, &s);

    	// Base Cycle
    	msg_printf(I, "Completed! Server in RUN...");

        int tick = 0;
    	for(;;)
    	{
    		rc = modbus_receive(ctx, query);

    		if(rc > 0)
    		{
    			//printf("[q] - %s\n", query);
    			modbus_reply(ctx, query, rc, mb_mapping);
    		}
    		else if(rc == -1)
    		{
    			// todo: Closce or error conection.
    			break;
    		}

    		tick++;

    		if(tick == 5)
    		{
    				mb_mapping->tab_input_bits[0] = 0;
    		}
    		else if(tick == 10)
    		{
    				mb_mapping->tab_input_bits[0] = 1;
    		}
    		else if(tick > 11)
    		{
    				tick = 0;
    		}

    		mb_mapping->tab_input_registers[0] = tick;
    	}

    	printf("[!] - Quit the loop: %s\n", modbus_strerror(errno));

    	modbus_mapping_free(mb_mapping);
    	if(s != -1)
    	{
    		close(s);
    	}

    	modbus_close(ctx);
    	modbus_free(ctx);

    	printf("[>] - Exit programm...\n");

    	return 0;
    }


